package com.asiainfo.rt.execution.application;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.ServerSocket;
import java.net.Socket;

public class AppMain {
	private static final String PROPERTY_PORT_NUMBER = "idea.launcher.port";
	private static final String PROPERTY_BINPATH = "idea.launcher.bin.path";

	private static native void triggerControlBreak();

	public static void main(String[] args) throws Throwable {
		final int portNumber = Integer.getInteger(PROPERTY_PORT_NUMBER)
				.intValue();
		Thread t = new Thread(new Runnable() {

			public void run() {
				try {
					ServerSocket socket = new ServerSocket(portNumber);
					Socket client = socket.accept();
					BufferedReader reader = new BufferedReader(
							new InputStreamReader(client.getInputStream()));
					while (true) {
						String msg = reader.readLine();

						if ("TERM".equals(msg)) {
							return;
						}
						if ("BREAK".equals(msg)) {
							AppMain.triggerControlBreak();
						} else if ("STOP".equals(msg))
							System.exit(1);
					}
				} catch (IOException ignored) {
				} catch (IllegalArgumentException ignored) {
				} catch (SecurityException ignored) {
				}
			}
		});

		try {
			t.setDaemon(true);
			t.start();
		} catch (Exception ignored) {
		}
		String mainClass = args[0];
		String[] parms = new String[args.length - 1];
		for (int j = 1; j < args.length; j++) {
			parms[(j - 1)] = args[j];
		}
		Method m = Class.forName(mainClass).getMethod("main",
				new Class[] { parms.getClass() });
		if (!Modifier.isStatic(m.getModifiers())) {
			System.err.println("main method should be static");
			return;
		}
		try {
			ensureAccess(m);
			m.invoke(null, new Object[] { parms });
		} catch (InvocationTargetException ite) {
			throw ite.getTargetException();
		}
	}

	private static void ensureAccess(Object reflectionObject) {
		Class<? extends Object> aClass = reflectionObject.getClass();
		try {
			Method setAccessibleMethod = aClass.getMethod("setAccessible",
					new Class[] { Boolean.TYPE });
			setAccessibleMethod.invoke(reflectionObject,
					new Object[] { Boolean.TRUE });
		} catch (Exception e) {
		}
	}

	static {
		String binPath = System.getProperty(PROPERTY_BINPATH) + File.separator;
		System.getProperty("os.name").toLowerCase();
		System.getProperty("os.arch").toLowerCase();

	}

	private AppMain() {
	}
}